/******************************************************************
 * Created by: DO HOANG HAI                                       
 * Date of Creation: 14/Jan/2008                                              
 * Date of last modification: 29/Dec/2007
 *                                                                
 * Description: Event argument to notify that the program has receive
 * search result from the network.
 * 
 ******************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Xml;
using System.Xml.Serialization;
using Pbdms.NetworkDealer.EventArgs;
using Pbdms.NetworkDealer.Requests;
using Pbdms.NetworkDealer.Utilities;

namespace Pbdms.NetworkDealer
{
    /// <summary>
    /// this class's responsibility is to deal with any incomming messages from the network
    /// as well as sending out messages, cooperate with Network Controller to perform 
    /// other realted functions
    /// </summary>
    public class NetworkDealer
    {
        System.Collections.ArrayList arlOfReceivedRequest;
        
        public const int SEARCH_REQUEST = 1;
        public const int DOWNLOAD_REQUEST = 2;
        public const int SEARCH_RESULT = 3;
        public const int DOWNLOAD_REQUEST_GRANTED = 4;
        public const int DOWNLOAD_REQUEST_REJECTED = 5;
        public const int DOWNLOAD_CLIENT_READY = 6;
        public const int BROWSE_REQUEST = 7;
        public const int BROWSE_RESULT_BUDDY = 8;
        public const int BROWSE_RESULT_ITEMS = 9;


        //listen port
        public const int LISTEN_PORT = 5150;
        public const int DOWNLOAD_PORT1 = 5151;
        public const int DOWNLOAD_PORT2 = 5152;
        public const int DOWNLOAD_PORT3 = 5153;
        //ipEndpoint and listener's socket

        //two files to be downloaded when a download request is sent to server.
        public String currentFileToDownload1;
        public String currentFileToDownload2;
        
        IPEndPoint ipEPListener;
        Socket sktTcpServer;
        public static IPAddress ipAddMyComputer = System.Net.Dns.GetHostAddresses(System.Net.Dns.GetHostName())[0];

        //delegate which handles the event
        /// <summary>
        /// define a handler for DownloadRequestreceived event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void DownloadRequestReceivedEventHandler(object sender, DownloadRequestReceivedEventArgs e);
        /// <summary>
        /// define a handler for SearchRequestreceived event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void SearchRequestReceivedEventHandler(object sender, SearchRequestReceivedEventArgs e);
        /// <summary>
        /// define a handler for SearchResultReceived event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void SearchResultReceivedEventHandler(object sender, SearchResultReceivedEventArgs e);
        /// <summary>
        /// define a handler for DownloadClientReady event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void DownloadClientReadyEventHandler(object sender, Pbdms.NetworkDealer.EventArgs.DownloadClientReadyEventArgs e);

        public delegate void BrowseRequestReceivedEventHandler(object sender, Pbdms.NetworkDealer.EventArgs.BrowseRequestReceivedEventArgs e);

        public delegate void BrowseResultBuddyReceivedEventHandler(object sender, Pbdms.NetworkDealer.EventArgs.BrowseResultBuddyReceivedEventArgs e);

        /// <summary>
        /// An event to be triggered when the application receives a message from the network
        /// </summary> 
        public event DownloadRequestReceivedEventHandler DownloadRequestReceived;
        /// <summary>
        /// Defines SearchRequestReceived event
        /// </summary>
        public event SearchRequestReceivedEventHandler SearchRequestReceived;
        /// <summary>
        /// deifnes SearchResultlReceived event
        /// </summary>
        public event SearchResultReceivedEventHandler searchResultReceived;
        /// <summary>
        /// defines DownloadClientReady event
        /// </summary>
        public event DownloadClientReadyEventHandler downloadClientReady;
        /// <summary>
        /// defines BrowseRequestReceived event
        /// </summary>
        public event BrowseRequestReceivedEventHandler browseRequestReceived;

        public event BrowseResultBuddyReceivedEventHandler browseResultBuddyReceived;

        public NetworkDealer()
        {
            arlOfReceivedRequest = new System.Collections.ArrayList();
            System.Threading.ThreadStart thsOldRequestRemover = new System.Threading.ThreadStart(removeOldRequest);
            System.Threading.Thread thOldRequestRemover = new System.Threading.Thread(thsOldRequestRemover);
            thOldRequestRemover.Start();
        }
        /// <summary>
        /// remove old request upon timeout
        /// </summary>
        public void removeOldRequest()
        {
            System.Timers.Timer tmer = new System.Timers.Timer(5000);
            tmer.Elapsed += new System.Timers.ElapsedEventHandler(tmer_Elapsed);
            tmer.Start();
        }
        /// <summary>
        /// handles Elapsed event triggered by the timer
        /// Tasks: check old requests and remove them from the list of requests
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void tmer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (arlOfReceivedRequest.Count > 0)
            {
                ReceivedRequest[] arrTemp = new ReceivedRequest[arlOfReceivedRequest.Count];
                arlOfReceivedRequest.CopyTo(arrTemp);
                for (int i = 0; i < arrTemp.Length; i++)
                {
                    ReceivedRequest rRequest = (ReceivedRequest)(arrTemp[i]);
                    if (DateTime.Now.Ticks - rRequest.ReceivedTime.Ticks > 30)
                    {
                        rRequest = null;
                    }
                }
                arlOfReceivedRequest = new System.Collections.ArrayList();
                for (int i = 0; i < arrTemp.Length; i++)
                {
                    if (arrTemp[i] != null)
                    {
                        arlOfReceivedRequest.Add(arrTemp[i]);
                    }
                }
            }
                        
        }

        /// <summary>
        /// force the program to stop listening on the port
        /// </summary>
        public void stopListening()
        {
            if (sktTcpServer != null)
            {
                sktTcpServer.Close();
                sktTcpServer = null;
            }
        }

        /// <summary>
        /// trigger the event
        /// </summary>
        /// <param name="networkDealer"></param>
        /// <param name="networkInfoEventArgs"></param>
        protected void onDownloadRequestReceived(object networkDealer, DownloadRequestReceivedEventArgs downloadRequestReceivedEventArgs)
        {
            //check if there are any subcriber
            if (DownloadRequestReceived != null)
            {
                //call the event
                DownloadRequestReceived(networkDealer, downloadRequestReceivedEventArgs);
            }
        }
        protected void onDownloadClientReady(object networkDealer, Pbdms.NetworkDealer.EventArgs.DownloadClientReadyEventArgs e)
        {
            if (e != null)
                downloadClientReady(networkDealer, e);
        }

        protected void onBrowseResultBuddyReceived(object networkDealer, Pbdms.NetworkDealer.EventArgs.BrowseResultBuddyReceivedEventArgs e)
        {
            if (e != null)
                browseResultBuddyReceived(networkDealer, e);
        }
        /// <summary>
        /// trigger the SearchRequestReceived event
        /// </summary>
        /// <param name="networkDealer"></param>
        /// <param name="searchRequestEventArgs"></param>
        protected void onSearchRequestReceived(object networkDealer, SearchRequestReceivedEventArgs searchRequestReceivedEventArgs)
        {
            if (searchRequestReceivedEventArgs != null)
            {
                //call the event
                SearchRequestReceived(networkDealer, searchRequestReceivedEventArgs);
            }
        }

        /// <summary>
        /// trigger the SearchResultReceived event
        /// </summary>
        /// <param name="networkDealer"></param>
        /// <param name="searchResultReceivedEventArgs"></param>
        protected void onSearchResultReceived(object networkDealer, SearchResultReceivedEventArgs searchResultReceivedEventArgs)
        {
            if (searchResultReceivedEventArgs != null)
            {
                //trigger the event
                searchResultReceived(networkDealer, searchResultReceivedEventArgs);
            }
        }

        protected void onBrowseRequestReceived(object networkDealer, BrowseRequestReceivedEventArgs browseRequestReceivedEventArgs)
        {
            if (browseRequestReceivedEventArgs != null)
            {
                //trigger the event
                browseRequestReceived(networkDealer, browseRequestReceivedEventArgs);
            }
        }

        /// <summary>
        /// start listening on the specified port
        /// </summary>
        public void startListening()
        {
            try
            {
                ipEPListener = new IPEndPoint(IPAddress.Any, LISTEN_PORT);
                sktTcpServer = new Socket(ipEPListener.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                sktTcpServer.Bind(ipEPListener);
                sktTcpServer.Listen(int.MaxValue);

                //start accepting
                Socket tcpClient;
                byte[] receiveBuffer = new byte[16384];
                while (true)
                {
                    try
                    {
                        tcpClient = sktTcpServer.Accept();
                        try
                        {
                            while (true)
                            {
                                int rc = tcpClient.Receive(receiveBuffer);
                                if (rc == 0)
                                    break; //empty message
                                else
                                {
                                    //get IP of sender
                                    EndPoint ep = tcpClient.RemoteEndPoint;
                                    IPAddress ipAdd = IPAddress.Parse(ep.ToString().Substring(0, ep.ToString().LastIndexOf('.')));

                                    //get message to an array of arguments
                                    string msg = System.Text.Encoding.ASCII.GetString(receiveBuffer);
                                    tcpClient.Close();
                                    processReceivedMessage(ipAdd, msg);
                                    //clear the buffer
                                    receiveBuffer = new byte[16384];
                                    //dlgNetworkMessageProcessor msgProcessor = new dlgNetworkMessageProcessor(processNetworkMessage);
                                    //object[] args1 = new object[2];
                                    //args1[0] = ipAdd;
                                    //args2[2] = msg;
                                    //this.Invoke(msgProcessor);

                                }
                            }
                        }
                        catch
                        {
                        }
                        finally
                        {
                            tcpClient.Close();
                        }
                    }
                    catch
                    {
                    }
                }
            }
            catch (SocketException)
            {
                Common.Global.showMsgOneButton("The application can't listen on the port 5150, it has been occupied by another process\r\nClose this process then restart the program.", 'C');
            }
        }

        /// <summary>
        /// check a request to see whether it is a duplicated request
        /// </summary>
        /// <param name="rRequest"></param>
        /// <returns></returns>
        private bool isDuplicatedRequest(ReceivedRequest rRequest)
        {
            if (arlOfReceivedRequest.Count > 0)
            {
                for (int i = 0; i < arlOfReceivedRequest.Count; i++)
                {
                    ReceivedRequest oldRequest = (ReceivedRequest)(arlOfReceivedRequest[i]);
                    if (rRequest.IpFrom.Equals(oldRequest.IpFrom) && rRequest.RequestId == oldRequest.RequestId)
                        return true;
                }
            }
            return false;
        }

        /// <summary>
        /// when the program receives a message from the network, this method will be called
        /// to decide what type of message, form the data and specify who will be responsible
        /// for this message.
        /// </summary>
        /// <param name="ipAdd"></param>
        /// <param name="msg"></param>
        private void processReceivedMessage(IPAddress ipAdd, string msg)
        {

            //extract the string, get the first character to see the data: what type of message and the xml data inside the message
            int msgType = int.Parse(msg.Substring(0, 1));
            msg = msg.Substring(1, msg.Length - 1);
            switch (msgType)
            {
                case DOWNLOAD_REQUEST:
                    {
                        handleDownLoadRequest(ipAdd, msg);
                        break;
                    }
                case SEARCH_REQUEST :
                    {
                        handleSearchRequest(ipAdd, msg);
                        break;
                    }

                case SEARCH_RESULT :
                    {
                        handleSearchResult(ipAdd,msg);
                        break;
                    }
                case DOWNLOAD_REQUEST_GRANTED:
                    {
                        handleDownLoadRequestGranted(ipAdd, msg);        
                        break;
                    }
                case DOWNLOAD_REQUEST_REJECTED:
                    {
                        handleDownLoadRequestRejected(ipAdd, msg);                        
                        break;
                    }
                case DOWNLOAD_CLIENT_READY:
                    {
                        handleDownloadClientReady(ipAdd, msg);
                        break;
                    }
                case BROWSE_REQUEST:
                    {
                        handleBrowseRequest(ipAdd, msg);
                        break;
                    }
                case BROWSE_RESULT_ITEMS:
                    {
                        handleBrowseResultItemReceived(ipAdd, msg);
                        break;
                    }
                case BROWSE_RESULT_BUDDY:
                    {
                        handleBrowseResultBuddyReceived(ipAdd, msg);
                        break;
                    }
            }            
        }

        private void handleBrowseResultBuddyReceived(IPAddress ipAdd, string msg)
        {
            BrowseResultBuddyReceivedEventArgs e = new BrowseResultBuddyReceivedEventArgs(msg);
            onBrowseResultBuddyReceived(this, e);
        }

        private void handleBrowseResultItemReceived(IPAddress ipAdd, string msg)
        {
            try
            {
                //deserialize to obtain the object
                System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(SearchResult));

                System.IO.StringReader strReader = new System.IO.StringReader(msg);
                SearchResult obj = (SearchResult)serializer.Deserialize(strReader);

                //form the event argument
                SearchResultReceivedEventArgs e = new SearchResultReceivedEventArgs(IPAddress.Parse(obj.ipAddResponder), obj.requestId, obj.arlResult);
                //trigger the event
                onSearchResultReceived(this, e);
            }
            catch (XmlException)
            {
            }
        }

        private void handleBrowseRequest(IPAddress ipAdd, string msg)
        {
            if (msg.Contains("\0"))
            {
                msg = msg.Substring(0, msg.IndexOf("\0")).Trim();
            }
            BrowseRequestReceivedEventArgs e = new BrowseRequestReceivedEventArgs(msg);
            onBrowseRequestReceived(this, e);
        }

        

        #region "handle message received"

        private void handleDownloadClientReady(IPAddress ipAdd, string msg)
        {
            if (msg.Contains("\0"))
            {
                msg = msg.Substring(0, msg.IndexOf("\0"));
            }
            msg = msg.Trim();
            string[] arrString = msg.Split(',');
            string ipSource = arrString[0];
            int clientPortNumber = int.Parse(arrString[1]);
            string itemId = arrString[2];
            string fileName = arrString[3];
            DownloadClientReadyEventArgs e = new DownloadClientReadyEventArgs(ipSource, clientPortNumber, itemId, fileName);
            onDownloadClientReady(this, e);
            
        }

        private void handleDownLoadRequestRejected(IPAddress ipAdd, string msg)
        {
            if (msg.Contains("\0"))
            {
                msg = msg.Substring(0, msg.IndexOf("\0"));
            }
            Common.Global.showMsgOneButton("The request to download the file " + msg+ " at "+ ipAdd.ToString()+ " has been rejected", 'I');
        }

        private void handleDownLoadRequestGranted(IPAddress ipAdd, string msg)
        {
            if (msg.Contains("\0"))
            {
                msg = msg.Substring(0, msg.IndexOf("\0"));
            }
            startDownloading(ipAdd, msg);
        }
        private void handleSearchRequest(IPAddress ipAdd, string msg)
        {
            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(SearchRequest));
                        
            System.IO.StringReader strReader = new System.IO.StringReader(msg);
            SearchRequest obj = (SearchRequest)serializer.Deserialize(strReader);

            ReceivedRequest rRequest = new ReceivedRequest(obj.requestId, DateTime.Now, IPAddress.Parse(obj.ipAddSource));
            if (!isDuplicatedRequest(rRequest))
            {
                arlOfReceivedRequest.Add(rRequest);
                //process the request by performing searching on local machine
                SearchRequestReceivedEventArgs e = new SearchRequestReceivedEventArgs(obj);
                //signal the event handler
                onSearchRequestReceived(this, e);
            }           
        }
        private void handleSearchResult(IPAddress ipAdd, string msg)
        {
            try
            {
                //deserialize to obtain the object
                System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(SearchResult));

                System.IO.StringReader strReader = new System.IO.StringReader(msg);
                SearchResult obj = (SearchResult)serializer.Deserialize(strReader);

                //form the event argument
                SearchResultReceivedEventArgs e = new SearchResultReceivedEventArgs(IPAddress.Parse(obj.ipAddResponder), obj.requestId, obj.arlResult);
                //trigger the event
                onSearchResultReceived(this, e);
            }
            catch (XmlException)
            {
            }
        }

        private void handleDownLoadRequest(IPAddress ipAdd, string msg)
        {
            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(DownloadRequest));

            System.IO.StringReader strReader = new System.IO.StringReader(msg);
            DownloadRequest obj = (DownloadRequest)serializer.Deserialize(strReader);

            //check the request for any duplication
            ReceivedRequest rRequest = new ReceivedRequest(obj.requestId, DateTime.Now, IPAddress.Parse(obj.ipAddSource ));
            if (!isDuplicatedRequest(rRequest))
            {
                arlOfReceivedRequest.Add(rRequest);
                //process the request by performing searching on local machine
                DownloadRequestReceivedEventArgs e = new DownloadRequestReceivedEventArgs(obj);
                onDownloadRequestReceived(this, e);
            }
            //else do nothing            
        }

        #endregion

        /// <summary>
        /// forward a search request to other direct buddies but not the one from which
        /// the message was sent
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="targetIPAdd"></param>
        public void forwardSearchRequest(SearchRequest obj,IPAddress targetIPAdd)
        {        
            obj.curHop++;
            obj.ipAddForwarder = ipAddMyComputer.ToString();

            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(obj.GetType());
            System.IO.StringWriter str = new System.IO.StringWriter();
            serializer.Serialize(str, obj);
            
            String s = SEARCH_REQUEST.ToString() + str.ToString();
            sendMessageToNetwork(s, targetIPAdd); 

        }
        /// <summary>
        /// get the id of the request
        /// </summary>
        /// <returns></returns>
        private int getRequestId()
        {
            DateTime dt = DateTime.Now;
            return int.Parse(dt.Hour.ToString() + dt.Minute.ToString() + dt.Second.ToString());
        }
        /// <summary>
        /// send a search request to the network (to all buddies)
        /// </summary>
        /// <param name="searchObj"></param>
        /// <param name="arlBuddies"></param>
        public void sendSearchRequest(Common.DataObject.SearchObj searchObj, System.Collections.ArrayList arlBuddies)
        {
            try
            {

                //form the SearchRequest object
                SearchRequest srq = new SearchRequest();
                srq.curHop = 0;
                srq.ipAddForwarder = null;
                srq.ipAddSource = ipAddMyComputer.ToString();
                srq.requestId = getRequestId();
                srq.searchObj = searchObj;

                //serialize the search object to xml string
                System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(srq.GetType());
                System.IO.StringWriter str = new System.IO.StringWriter();
                serializer.Serialize(str, srq);
                String s = SEARCH_REQUEST.ToString() + str.ToString();

                //send the request to all buddies
                if (arlBuddies != null)
                {
                    foreach (Common.DataObject.Buddy bdd in arlBuddies)
                    {
                        if (!bdd.IpAdd.Equals("") && !bdd.IpAdd.Equals(ipAddMyComputer.ToString()))
                        {
                            sendMessageToNetwork(s, IPAddress.Parse(bdd.IpAdd));
                        }
                    }
                }
            }
            catch
            {
                Common.Global.showMsgOneButton("An unexpected error has occurred, the program is unable to send the request.\r\nPlease try again latter!", 'W');
            }
        }

        /// <summary>
        /// send a message to all buddies
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="ipAdd"></param>
        public void sendMessageToNetwork(string msg, IPAddress ipAdd)
        {
            //create a thread to send the message to avoid and waiting
            object[] args = new object[] { msg, ipAdd };
            Sender s = new Sender(args);            
            System.Threading.ThreadStart thsSendMessage = new System.Threading.ThreadStart(s.sendMessagetoNetwork);
            System.Threading.Thread thSendMessage = new System.Threading.Thread(thsSendMessage);
            
            thSendMessage.Start();
            

        }
        /// <summary>
        /// send a Search result object to the requester
        /// </summary>
        /// <param name="arlResult"></param>
        /// <param name="e"></param>
        public void sendSearchResult(System.Collections.ArrayList arlResult,SearchRequestReceivedEventArgs e)
        {
            for (int i = 0; i < arlResult.Count; i++)
            {
                System.Collections.ArrayList arlTemp = new System.Collections.ArrayList();
                arlTemp.Add(arlResult[i]);
                //create SearchResult object
                SearchResult sr = new SearchResult(ipAddMyComputer.ToString(), e.SearchRequestObj.requestId, arlTemp);
                //serialize the object
                System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(SearchResult));
                System.IO.StringWriter str = new System.IO.StringWriter();
                serializer.Serialize(str, sr);
                String s = SEARCH_RESULT + str.ToString();
                //send it over the network
                sendMessageToNetwork(s, IPAddress.Parse(e.SearchRequestObj.ipAddSource));
            }            
        }

        public void sendBrowseResultItems(System.Collections.ArrayList arlResult, BrowseRequestReceivedEventArgs e)
        {
            for (int i = 0; i < arlResult.Count; i++)
            {
                System.Collections.ArrayList arlTemp = new System.Collections.ArrayList();
                arlTemp.Add(arlResult[i]);
                //create SearchResult object
                SearchResult sr = new SearchResult(ipAddMyComputer.ToString(), 0, arlTemp);
                //serialize the object
                System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(SearchResult));
                System.IO.StringWriter str = new System.IO.StringWriter();
                serializer.Serialize(str, sr);
                String s = BROWSE_RESULT_ITEMS + str.ToString();
                //send it over the network
                sendMessageToNetwork(s, IPAddress.Parse(e.ipAddSource));
            }    
        }
        /// <summary>
        /// send the buddy string to the requester
        /// </summary>
        /// <param name="strBuddies"></param>
        /// <param name="e"></param>
        public void sendBrowseResultBuddy(String strBuddies, BrowseRequestReceivedEventArgs e)
        {
            sendMessageToNetwork(BROWSE_RESULT_BUDDY.ToString() + " " + strBuddies, IPAddress.Parse(e.ipAddSource));
        }

        /// <summary>
        /// send a file to the client - the requester
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="fileInfoObj"></param>
        /// <param name="downloadRequestObj"></param>
        public void sendFileToClient(String msg, Pbdms.Common.DataObject.FileInfo fileInfoObj, DownloadRequest downloadRequestObj)
        {
            //send a message to inform the client to listen on another port
            sendMessageToNetwork(msg, System.Net.IPAddress.Parse(downloadRequestObj.ipAddSource));

            //when the client is ready, start sending the file
            object[] args = new object[]{msg,System.Net.IPAddress.Parse(downloadRequestObj.ipAddSource)};
            Sender s = new Sender(args);
            s.sendMessagetoNetwork();
            //start sending the file
            System.Threading.ThreadStart thsSendMessage = new System.Threading.ThreadStart(s.sendFileToClient);
            System.Threading.Thread thSendMessage = new System.Threading.Thread(thsSendMessage);

            thSendMessage.Start();

        }

        #region "download file"

        /// <summary>
        /// send a Download Request
        /// </summary>
        /// <param name="itemId"></param>
        /// <param name="ipAddTarget"></param>
        public void sendDownloadRequest(string itemId, IPAddress ipAddTarget, String fileDownload1, String fileDownload2)
        {
            currentFileToDownload1 = fileDownload1;
            currentFileToDownload2 = fileDownload2;
            DownloadRequest dr = new DownloadRequest(ipAddMyComputer.ToString(), itemId, getRequestId());
            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(DownloadRequest));
            System.IO.StringWriter str = new System.IO.StringWriter();
            serializer.Serialize(str, dr);
            string msg = NetworkDealer.DOWNLOAD_REQUEST.ToString() + str;
            sendMessageToNetwork(msg, ipAddTarget);
        }
        /// <summary>
        /// send a DownloadResponse_Granted message to the requester
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="ipAddTarget"></param>
        public void sendDownloadResponse_Granted(string msg, IPAddress ipAddTarget)
        {            
            msg = NetworkDealer.DOWNLOAD_REQUEST_GRANTED.ToString() +  " " + ipAddMyComputer.ToString()+"," + msg ;
            sendMessageToNetwork(msg, ipAddTarget);
        }
        /// <summary>
        /// send a reject signal to the requester
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="ipAddTarget"></param>
        public void sendDownloadResponse_Rejected(string msg, IPAddress ipAddTarget)
        {
            msg = NetworkDealer.DOWNLOAD_REQUEST_REJECTED.ToString() + " " + msg;
            sendMessageToNetwork(msg, ipAddTarget);

        }
        /// <summary>
        /// start downloading a file
        /// </summary>
        /// <param name="ipAdd"></param>
        /// <param name="msg"></param>
        public void startDownloading(IPAddress ipAdd, string msg)
        {
            
            string[] arrStr = msg.Trim().Split(',');
            string itemId = arrStr[1];
            string ipSource = arrStr[0];
            long fileSize1 = long.Parse(arrStr[2].Trim());
//            string fileName1 = arrStr[3];
            string fileName1 ;
            if (currentFileToDownload1.Contains(arrStr[3].Substring(0,arrStr[3].IndexOf("."))))
                fileName1 = currentFileToDownload1;
            else
                fileName1 = currentFileToDownload2;
            
            //start download the file
            Pbdms.NetworkDealer.Utilities.FileDownloader fdl = new Pbdms.NetworkDealer.Utilities.FileDownloader(fileName1, arrStr[3], fileSize1, itemId, IPAddress.Parse(ipSource));
            System.Threading.ThreadStart thsDownload = new System.Threading.ThreadStart(fdl.download);
            System.Threading.Thread thDownloader = new System.Threading.Thread(thsDownload);
            thDownloader.Start();
            if (arrStr.Length > 5)
            {
                while (true)
                {
                    if (thDownloader.ThreadState != System.Threading.ThreadState.Running)
                    {
                        long fileSize2 = long.Parse(arrStr[4].Trim());
                        //string fileName2 = arrStr[5];
                        string fileName2;
                        if (currentFileToDownload2.Contains(arrStr[5].Substring(0, arrStr[5].IndexOf("."))))
                            fileName2 = currentFileToDownload2;
                        else
                            fileName2 = currentFileToDownload1;
                        //start download the file
                        Pbdms.NetworkDealer.Utilities.FileDownloader fdl2 = new Pbdms.NetworkDealer.Utilities.FileDownloader(fileName2, arrStr[5], fileSize2, itemId, IPAddress.Parse(ipSource));
                        System.Threading.ThreadStart thsDownload2 = new System.Threading.ThreadStart(fdl2.download);
                        System.Threading.Thread thDownloader2 = new System.Threading.Thread(thsDownload2);
                        thDownloader2.Start();
                        break;
                    }
                }
            }            
        }
        /// <summary>
        /// start sending f afile
        /// </summary>
        /// <param name="clientIpAdd"></param>
        /// <param name="clientPort"></param>
        /// <param name="filePath"></param>
        public void sendFile(string clientIpAdd, int clientPort, string filePath)
        {
            object[] args = new object[3];
            args[0] = clientIpAdd;
            args[1] = clientPort;
            args[2] = filePath;
            Sender s = new Sender(args);
            System.Threading.ThreadStart thsFileSender = new System.Threading.ThreadStart(s.sendFileToClient);
            System.Threading.Thread thFileSender = new System.Threading.Thread(thsFileSender);
            thFileSender.Start();

        }
        #endregion




        public void sendBrowseRequest(IPAddress ipAdd)
        {
            String msg = NetworkDealer.BROWSE_REQUEST.ToString() + " " + ipAddMyComputer.ToString();
            sendMessageToNetwork(msg, ipAdd);
        }
    }
}
